package com.exam.online.system.service.impl;

import com.exam.online.system.constant.StatusCode;
import com.exam.online.system.dao.*;
import com.exam.online.system.entity.*;
import com.exam.online.system.model.GetPaperDetailsModel;
import com.exam.online.system.model.PaperListModel;
import com.exam.online.system.model.QuestionDetilsModel;
import com.exam.online.system.model.StuentScoreModel;
import com.exam.online.system.model.request.PaperSubmitModel;
import com.exam.online.system.model.request.ReviewPaperModel;
import com.exam.online.system.service.PaperService;
import com.exam.online.system.util.PageModel;
import com.exam.online.system.util.ResponseModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author yuzhen
 * @date 2019/5/6
 */
@Service
public class PaperServiceImpl implements PaperService {

    @Autowired
    PaperDAO paperDAO;
    @Autowired
    QuestionDAO questionDAO;
    @Autowired
    QuestionStuPaperDAO questionStuPaperDAO;
    @Autowired
    StuPaperDAO stuPaperDAO;
    @Autowired
    StuCourseRelationDAO stuCourseRelationDAO;
    @Autowired
    TeacherCourseDAO teacherCourseDAO;
    @Autowired
    CoursePaperDAO coursePaperDAO;
    @Autowired
    StudentDAO studentDAO;
    @Autowired
    CourseDAO courseDAO;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Paper savePaper(String name, String content, String courseName, Integer teacherId, Integer testTime, String questionIds) {
        Course course = courseDAO.selectByCourseName(courseName);
        Paper paper = new Paper();
        paper.setName(name);
        paper.setContent(content);
        paper.setCourseId(course.getId());
        paper.setTeacherId(teacherId);
        paper.setTestTime(testTime);
        String[] questionIdStrings = questionIds.split(",");
        int fullMark = 0;
        StringBuilder choiceQuestion = new StringBuilder();
        StringBuilder judgeQuestion = new StringBuilder();
        StringBuilder shortQuestion = new StringBuilder();
        for (String questionId : questionIdStrings) {
            Question question = questionDAO.selectByPrimaryKey(Integer.parseInt(questionId));
            if (question.getType() == 1) {
                choiceQuestion.append(questionId).append(",");
            } else if (question.getType() == 2) {
                judgeQuestion.append(questionId).append(",");
            } else {
                shortQuestion.append(questionId).append(",");
            }
            fullMark += question.getScore();
        }
        paper.setQuestionId(choiceQuestion.toString() + judgeQuestion.toString() + shortQuestion.toString());
        paper.setFullMark(fullMark);
        int insert = paperDAO.insert(paper);
        if (insert > 0) {
            return paper;
        } else {
            return null;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseModel calculateScore(Integer userId, Integer paperId, List<PaperSubmitModel.QuestionAnswerModel> model) {
        //先查询的question，获取答案，然后对比选择题和判断题是否得分
        //插入question_stu_paper表，同时计算选择题分数和判断题分数
        //最后更新stu_paper表
        AtomicInteger totalScore = new AtomicInteger();
        model.forEach(e -> {
            Integer questionId = e.getQuestionId();
            Question question = questionDAO.selectByPrimaryKey(questionId);
            if (question != null) {
                QuestionStuPaper questionStuPaper = new QuestionStuPaper();
                questionStuPaper.setPaperId(paperId);
                questionStuPaper.setQuestionId(questionId);
                questionStuPaper.setStuAnswer(e.getAnswer());
                questionStuPaper.setStuId(userId);
                if (question.getType() != 3) {
                    if (question.getAnswer().equals(e.getAnswer())) {
                        questionStuPaper.setScore(question.getScore());
                        totalScore.addAndGet(question.getScore());
                    } else {
                        questionStuPaper.setScore(0);
                    }
                } else {
                    questionStuPaper.setScore(null);
                }
                questionStuPaperDAO.insert(questionStuPaper);
            }
        });
        StuPaper stuPaper = stuPaperDAO.selectByPaperIdAndStuId(paperId, userId);
        stuPaper.setScore(totalScore.get());
        stuPaper.setIsExam(1);
        stuPaperDAO.updateByPrimaryKey(stuPaper);
        return ResponseModel.buildFromStateCode(StatusCode.SUCCESS);
    }

    @Override
    public PageModel listUnExamPaper(Integer stuId, Integer pageNo, Integer pageSize) {
        PageModel<PaperListModel> pageModel = new PageModel<>();
        pageModel.setPageNo(pageNo);
        pageModel.setPageSize(pageSize);
        List<StuPaper> stuPapers = stuPaperDAO.listUnExamPaper(stuId, 0, (pageNo - 1) * pageSize, pageSize);
        List<PaperListModel> paperListModelList = new ArrayList<>();
        for (StuPaper stuPaper : stuPapers) {
            Paper paper = paperDAO.selectByPrimaryKey(stuPaper.getPaperId());
            PaperListModel paperListModel = new PaperListModel();
            paperListModel.setName(paper.getName());
            paperListModel.setContent(paper.getContent());
            paperListModel.setPaperId(paper.getId());
            paperListModel.setFullMark(paper.getFullMark());
            paperListModel.setIsCorrect(stuPaper.getIsCorrect());
            paperListModel.setIsExam(stuPaper.getIsExam());
            paperListModel.setTestTime(paper.getTestTime());
            paperListModelList.add(paperListModel);
        }
        int total = stuPaperDAO.totalByStuIdAndIsExam(stuId, 0);
        pageModel.setDatas(paperListModelList);
        pageModel.setTotalPages(total / pageSize + 1);
        pageModel.setTotalRecords(total);
        return pageModel;
    }

    @Override
    public PageModel listIsExamPaper(Integer stuId, Integer pageNo, Integer pageSize) {
        PageModel<PaperListModel> pageModel = new PageModel<>();
        pageModel.setPageNo(pageNo);
        pageModel.setPageSize(pageSize);
        List<StuPaper> stuPapers = stuPaperDAO.listUnExamPaper(stuId, 1, (pageNo - 1) * pageSize, pageSize);
        List<PaperListModel> paperListModelList = new ArrayList<>();
        for (StuPaper stuPaper : stuPapers) {
            Paper paper = paperDAO.selectByPrimaryKey(stuPaper.getPaperId());
            PaperListModel paperListModel = new PaperListModel();
            paperListModel.setName(paper.getName());
            paperListModel.setContent(paper.getContent());
            paperListModel.setPaperId(paper.getId());
            paperListModel.setFullMark(stuPaper.getScore());
            paperListModel.setIsExam(stuPaper.getIsExam());
            paperListModel.setIsCorrect(stuPaper.getIsCorrect());
            paperListModel.setTestTime(paper.getTestTime());
            paperListModelList.add(paperListModel);
        }
        int total = stuPaperDAO.totalByStuIdAndIsExam(stuId, 1);
        pageModel.setDatas(paperListModelList);
        pageModel.setTotalPages(total / pageSize + 1);
        pageModel.setTotalRecords(total);
        return pageModel;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseModel issuePaper(Integer paperId) {
        /*
         * 1.paperId查找courseId
         * 2.courseId查找stuIds
         * 3.保存paperId和stuIds的关系
         */
        Paper paper = paperDAO.selectByPrimaryKey(paperId);
        List<Integer> stuIds = stuCourseRelationDAO.selectByCourseId(paper.getCourseId());
        Date date = new Date();
        stuIds.forEach(stuId -> {
            //当重复发布试卷的时候，可以去掉已经保存发布试卷的数据，防止重复保存
            StuPaper stuPaper1 = stuPaperDAO.selectByPaperIdAndStuId(paperId, stuId);
            if (stuPaper1 != null) {
                return;
            }
            StuPaper stuPaper = new StuPaper();
            stuPaper.setPaperId(paperId);
            stuPaper.setStuId(stuId);
            stuPaper.setScore(null);
            stuPaper.setIsCorrect(2);
            stuPaper.setIsExam(0);
            stuPaper.setState(1);
            stuPaper.setCreateTime(date);
            stuPaperDAO.insert(stuPaper);
        });
        return ResponseModel.buildFromStateCode(StatusCode.SUCCESS);
    }

    @Override
    public ResponseModel getPaperDetail(Integer paperId) {
        Paper paper = paperDAO.selectByPrimaryKey(paperId);
        GetPaperDetailsModel getPaperDetailsModel = new GetPaperDetailsModel();
        getPaperDetailsModel.setContent(paper.getContent());
        getPaperDetailsModel.setName(paper.getName());
        getPaperDetailsModel.setTestTime(paper.getTestTime());
        String questionId = paper.getQuestionId();
        String[] questionList = questionId.split(",");
        List<QuestionDetilsModel> questionDetailsModelList = new ArrayList<>();
        for (String question : questionList) {
            QuestionDetilsModel questionDetilsModel = new QuestionDetilsModel();
            Question question1 = questionDAO.selectByPrimaryKey(Integer.valueOf(question));
            questionDetilsModel.setOptiona(question1.getOptiona());
            questionDetilsModel.setOptionb(question1.getOptionb());
            questionDetilsModel.setOptionc(question1.getOptionc());
            questionDetilsModel.setOptiond(question1.getOptiond());
            questionDetilsModel.setQuestionId(question1.getId());
            questionDetilsModel.setScore(question1.getScore());
            questionDetilsModel.setTitle(question1.getTitle());
            questionDetilsModel.setType(question1.getType());
            questionDetailsModelList.add(questionDetilsModel);
        }
        getPaperDetailsModel.setQuestionDetilsModels(questionDetailsModelList);
        return ResponseModel.buildFromStateCode(StatusCode.SUCCESS, getPaperDetailsModel);
    }

    @Override
    public ResponseModel checkMarks(Integer paperId, Integer stuId) {
        List<QuestionStuPaper> questionStuPaperList = questionStuPaperDAO.findByStuIdAndPaperId(stuId, paperId);
        Map<Integer, QuestionStuPaper> questionId2QuestionMap = new HashMap<>();
        questionStuPaperList.forEach(e -> {
            questionId2QuestionMap.put(e.getQuestionId(), e);
        });
        Paper paper = paperDAO.selectByPrimaryKey(paperId);
        GetPaperDetailsModel getPaperDetailsModel = new GetPaperDetailsModel();
        getPaperDetailsModel.setContent(paper.getContent());
        getPaperDetailsModel.setName(paper.getName());
        getPaperDetailsModel.setTestTime(paper.getTestTime());
        //题目id,用,隔开
        String questionId = paper.getQuestionId();
        String[] questionList = questionId.split(",");
        List<QuestionDetilsModel> questionDetilsModelList = new ArrayList<>();
        for (String question : questionList) {
            QuestionDetilsModel questionDetilsModel = new QuestionDetilsModel();
            Question question1 = questionDAO.selectByPrimaryKey(Integer.valueOf(question));
            questionDetilsModel.setOptiona(question1.getOptiona());
            questionDetilsModel.setOptionb(question1.getOptionb());
            questionDetilsModel.setOptionc(question1.getOptionc());
            questionDetilsModel.setOptiond(question1.getOptiond());
            questionDetilsModel.setQuestionId(question1.getId());
            if (questionId2QuestionMap.get(question1.getId()) != null) {
                questionDetilsModel.setStuAnswer(questionId2QuestionMap.get(question1.getId()).getStuAnswer());
                questionDetilsModel.setScore(questionId2QuestionMap.get(question1.getId()).getScore());
            }
            questionDetilsModel.setTitle(question1.getTitle());
            questionDetilsModel.setType(question1.getType());
            questionDetilsModelList.add(questionDetilsModel);
        }
        getPaperDetailsModel.setQuestionDetilsModels(questionDetilsModelList);
        return ResponseModel.buildFromStateCode(StatusCode.SUCCESS, getPaperDetailsModel);
    }

    @Override
    public void submitScore(ReviewPaperModel reviewPaperModel) {
        /*
         * 1.QuestionStuPaper更新问题的分数
         * 2.计算分数
         * 3.更新stuPaper的总分和变成已经批改
         */
        Integer paperId = reviewPaperModel.getPaperId();
        Integer stuId = reviewPaperModel.getStuId();
        List<ReviewPaperModel.QuestionAndScoreModel> questionModel = reviewPaperModel.getQuestionModel();
        StuPaper stuPaper = stuPaperDAO.selectByPaperIdAndStuId(paperId, stuId);
        AtomicInteger total = new AtomicInteger();
        questionModel.forEach(e -> {
            QuestionStuPaper questionStuPaper = questionStuPaperDAO.selectByPaperIdAndStuIdAndQuestionId(paperId, stuId, e.getQuestionId());
            questionStuPaper.setScore(e.getScore());
            questionStuPaperDAO.updateByPrimaryKey(questionStuPaper);
            total.addAndGet(e.getScore());
        });
        stuPaper.setScore(stuPaper.getScore() + total.get());
        stuPaper.setIsCorrect(1);
        stuPaperDAO.updateByPrimaryKey(stuPaper);
    }

    @Override
    public PageModel findPaperByTeacherId(Integer teacherId, Integer pageNo, Integer pageSize) {
        List<Paper> papers = paperDAO.selectByTeacherId(teacherId, (pageNo - 1) * pageSize, pageSize);
        int total = paperDAO.totalByTeacherId(teacherId);
        PageModel pageModel = new PageModel();
        pageModel.setPageSize(pageSize);
        pageModel.setPageNo(pageNo);
        pageModel.setDatas(papers);
        pageModel.setTotalPages(total / pageSize + 1);
        pageModel.setTotalRecords(total);
        return pageModel;
    }

    @Override
    public PageModel stuScoreList(Integer teacherId, Integer pageNo, Integer pageSize) {
        /*
         * 1.通过老师查找所教的课程
         * 2.通过课程查找试卷
         * 3.通过试卷查找所有的stu_paper
         */
        List<Integer> courseIds = teacherCourseDAO.selectByTeacherId(teacherId);
        List<CoursePaper> paperList = new ArrayList<>();
        courseIds.forEach(e -> {
            paperList.addAll(coursePaperDAO.selectByCourseId(e));
        });
        List<Student> students = studentDAO.selectAll();
        Map<Integer, Student> studentMap = new HashMap<>();
        students.forEach(e -> {
            studentMap.put(e.getId(), e);
        });
        List<StuentScoreModel> stuentScoreModels = new ArrayList<>();
        paperList.forEach(coursePaper -> {
            //查找学生和试卷的关系
            List<StuPaper> stuPapers = stuPaperDAO.selectByPaperId(coursePaper.getPaperId());
            Paper paper = paperDAO.selectByPrimaryKey(coursePaper.getPaperId());
            stuPapers.forEach(e -> {
                Student student = studentMap.get(e.getStuId());
                StuentScoreModel stuentScoreModel = new StuentScoreModel();
                stuentScoreModel.setPaperId(coursePaper.getPaperId());
                stuentScoreModel.setPaperName(paper.getName());
                stuentScoreModel.setIsCorrect(e.getIsCorrect());
                stuentScoreModel.setScore(e.getScore());
                stuentScoreModel.setStuId(student.getId());
                stuentScoreModel.setStuName(student.getName());
                stuentScoreModel.setStuNum(student.getStuNum());
                stuentScoreModels.add(stuentScoreModel);
            });
        });
        PageModel pageModel = new PageModel();
        pageModel.setPageNo(pageNo);
        pageModel.setPageSize(pageSize);
        pageModel.setTotalRecords(stuentScoreModels.size());
        int start = 0;
        List<StuentScoreModel> result = new ArrayList<>();
        for (StuentScoreModel stuentScoreModel : stuentScoreModels) {
            if (start < (pageNo - 1) * pageSize) {
                continue;
            }
            if (start >= (pageNo - 1) * pageSize + pageSize) {
                break;
            }
            result.add(stuentScoreModel);
            start++;
        }
        pageModel.setDatas(result);
        pageModel.setTotalPages(stuentScoreModels.size() / pageSize + 1);
        return pageModel;
    }
}
